/*
 * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */
package com.sun.java.swing.plaf.motif;

import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.border.*;
import javax.swing.plaf.basic.*;
import java.io.Serializable;
import java.awt.event.*;
import java.beans.*;

/**
 * ComboBox motif look and feel
 * <p> * <strong>Warning:</strong>
 * Serialized objects of this class will not be compatible with
 * future Swing releases.  The current serialization support is appropriate
 * for short term storage or RMI between applications running the same
 * version of Swing.  A future release of Swing will provide support for
 * long term persistence.
 *
 * @author Arnaud Weber
 */
public class MotifComboBoxUI extends BasicComboBoxUI implements Serializable {

  Icon arrowIcon;
  static final int HORIZ_MARGIN = 3;

  public static ComponentUI createUI(JComponent c) {
    return new MotifComboBoxUI();
  }

  public void installUI(JComponent c) {
    super.installUI(c);
    arrowIcon = new MotifComboBoxArrowIcon(UIManager.getColor("controlHighlight"),
        UIManager.getColor("controlShadow"),
        UIManager.getColor("control"));

    Runnable initCode = new Runnable() {
      public void run() {
        if (motifGetEditor() != null) {
          motifGetEditor().setBackground(UIManager.getColor("text"));
        }
      }
    };

    SwingUtilities.invokeLater(initCode);
  }

  public Dimension getMinimumSize(JComponent c) {
    if (!isMinimumSizeDirty) {
      return new Dimension(cachedMinimumSize);
    }
    Dimension size;
    Insets insets = getInsets();
    size = getDisplaySize();
    size.height += insets.top + insets.bottom;
    int buttonSize = iconAreaWidth();
    size.width += insets.left + insets.right + buttonSize;

    cachedMinimumSize.setSize(size.width, size.height);
    isMinimumSizeDirty = false;

    return size;
  }

  protected ComboPopup createPopup() {
    return new MotifComboPopup(comboBox);
  }

  /**
   * Overriden to empty the MouseMotionListener.
   */
  protected class MotifComboPopup extends BasicComboPopup {

    public MotifComboPopup(JComboBox comboBox) {
      super(comboBox);
    }

    /**
     * Motif combo popup should not track the mouse in the list.
     */
    public MouseMotionListener createListMouseMotionListener() {
      return new MouseMotionAdapter() {
      };
    }

    public KeyListener createKeyListener() {
      return super.createKeyListener();
    }

    protected class InvocationKeyHandler extends BasicComboPopup.InvocationKeyHandler {

      protected InvocationKeyHandler() {
        MotifComboPopup.this.super();
      }
    }
  }

  protected void installComponents() {
    if (comboBox.isEditable()) {
      addEditor();
    }

    comboBox.add(currentValuePane);
  }

  protected void uninstallComponents() {
    removeEditor();
    comboBox.removeAll();
  }

  public void paint(Graphics g, JComponent c) {
    boolean hasFocus = comboBox.hasFocus();
    Rectangle r;

    if (comboBox.isEnabled()) {
      g.setColor(comboBox.getBackground());
    } else {
      g.setColor(UIManager.getColor("ComboBox.disabledBackground"));
    }
    g.fillRect(0, 0, c.getWidth(), c.getHeight());

    if (!comboBox.isEditable()) {
      r = rectangleForCurrentValue();
      paintCurrentValue(g, r, hasFocus);
    }
    r = rectangleForArrowIcon();
    arrowIcon.paintIcon(c, g, r.x, r.y);
    if (!comboBox.isEditable()) {
      Border border = comboBox.getBorder();
      Insets in;
      if (border != null) {
        in = border.getBorderInsets(comboBox);
      } else {
        in = new Insets(0, 0, 0, 0);
      }
      // Draw the separation
      if (MotifGraphicsUtils.isLeftToRight(comboBox)) {
        r.x -= (HORIZ_MARGIN + 2);
      } else {
        r.x += r.width + HORIZ_MARGIN + 1;
      }
      r.y = in.top;
      r.width = 1;
      r.height = comboBox.getBounds().height - in.bottom - in.top;
      g.setColor(UIManager.getColor("controlShadow"));
      g.fillRect(r.x, r.y, r.width, r.height);
      r.x++;
      g.setColor(UIManager.getColor("controlHighlight"));
      g.fillRect(r.x, r.y, r.width, r.height);
    }
  }

  public void paintCurrentValue(Graphics g, Rectangle bounds, boolean hasFocus) {
    ListCellRenderer renderer = comboBox.getRenderer();
    Component c;
    Dimension d;
    c = renderer
        .getListCellRendererComponent(listBox, comboBox.getSelectedItem(), -1, false, false);
    c.setFont(comboBox.getFont());
    if (comboBox.isEnabled()) {
      c.setForeground(comboBox.getForeground());
      c.setBackground(comboBox.getBackground());
    } else {
      c.setForeground(UIManager.getColor("ComboBox.disabledForeground"));
      c.setBackground(UIManager.getColor("ComboBox.disabledBackground"));
    }
    d = c.getPreferredSize();
    currentValuePane.paintComponent(g, c, comboBox, bounds.x, bounds.y,
        bounds.width, d.height);
  }

  protected Rectangle rectangleForArrowIcon() {
    Rectangle b = comboBox.getBounds();
    Border border = comboBox.getBorder();
    Insets in;
    if (border != null) {
      in = border.getBorderInsets(comboBox);
    } else {
      in = new Insets(0, 0, 0, 0);
    }
    b.x = in.left;
    b.y = in.top;
    b.width -= (in.left + in.right);
    b.height -= (in.top + in.bottom);

    if (MotifGraphicsUtils.isLeftToRight(comboBox)) {
      b.x = b.x + b.width - HORIZ_MARGIN - arrowIcon.getIconWidth();
    } else {
      b.x += HORIZ_MARGIN;
    }
    b.y = b.y + (b.height - arrowIcon.getIconHeight()) / 2;
    b.width = arrowIcon.getIconWidth();
    b.height = arrowIcon.getIconHeight();
    return b;
  }

  protected Rectangle rectangleForCurrentValue() {
    int width = comboBox.getWidth();
    int height = comboBox.getHeight();
    Insets insets = getInsets();
    if (MotifGraphicsUtils.isLeftToRight(comboBox)) {
      return new Rectangle(insets.left, insets.top,
          (width - (insets.left + insets.right)) -
              iconAreaWidth(),
          height - (insets.top + insets.bottom));
    } else {
      return new Rectangle(insets.left + iconAreaWidth(), insets.top,
          (width - (insets.left + insets.right)) -
              iconAreaWidth(),
          height - (insets.top + insets.bottom));
    }
  }

  public int iconAreaWidth() {
    if (comboBox.isEditable()) {
      return arrowIcon.getIconWidth() + (2 * HORIZ_MARGIN);
    } else {
      return arrowIcon.getIconWidth() + (3 * HORIZ_MARGIN) + 2;
    }
  }

  public void configureEditor() {
    super.configureEditor();
    editor.setBackground(UIManager.getColor("text"));
  }

  protected LayoutManager createLayoutManager() {
    return new ComboBoxLayoutManager();
  }

  private Component motifGetEditor() {
    return editor;
  }

  /**
   * This inner class is marked &quot;public&quot; due to a compiler bug.
   * This class should be treated as a &quot;protected&quot; inner class.
   * Instantiate it only within subclasses of <FooUI>.
   */
  public class ComboBoxLayoutManager extends BasicComboBoxUI.ComboBoxLayoutManager {

    public ComboBoxLayoutManager() {
      MotifComboBoxUI.this.super();
    }

    public void layoutContainer(Container parent) {
      if (motifGetEditor() != null) {
        Rectangle cvb = rectangleForCurrentValue();
        cvb.x += 1;
        cvb.y += 1;
        cvb.width -= 1;
        cvb.height -= 2;
        motifGetEditor().setBounds(cvb);
      }
    }
  }

  static class MotifComboBoxArrowIcon implements Icon, Serializable {

    private Color lightShadow;
    private Color darkShadow;
    private Color fill;

    public MotifComboBoxArrowIcon(Color lightShadow, Color darkShadow, Color fill) {
      this.lightShadow = lightShadow;
      this.darkShadow = darkShadow;
      this.fill = fill;
    }


    public void paintIcon(Component c, Graphics g, int xo, int yo) {
      int w = getIconWidth();
      int h = getIconHeight();

      g.setColor(lightShadow);
      g.drawLine(xo, yo, xo + w - 1, yo);
      g.drawLine(xo, yo + 1, xo + w - 3, yo + 1);
      g.setColor(darkShadow);
      g.drawLine(xo + w - 2, yo + 1, xo + w - 1, yo + 1);

      for (int x = xo + 1, y = yo + 2, dx = w - 6; y + 1 < yo + h; y += 2) {
        g.setColor(lightShadow);
        g.drawLine(x, y, x + 1, y);
        g.drawLine(x, y + 1, x + 1, y + 1);
        if (dx > 0) {
          g.setColor(fill);
          g.drawLine(x + 2, y, x + 1 + dx, y);
          g.drawLine(x + 2, y + 1, x + 1 + dx, y + 1);
        }
        g.setColor(darkShadow);
        g.drawLine(x + dx + 2, y, x + dx + 3, y);
        g.drawLine(x + dx + 2, y + 1, x + dx + 3, y + 1);
        x += 1;
        dx -= 2;
      }

      g.setColor(darkShadow);
      g.drawLine(xo + (w / 2), yo + h - 1, xo + (w / 2), yo + h - 1);

    }

    public int getIconWidth() {
      return 11;
    }

    public int getIconHeight() {
      return 11;
    }
  }

  /**
   * {@inheritDoc}
   *
   * @since 1.6
   */
  protected PropertyChangeListener createPropertyChangeListener() {
    return new MotifPropertyChangeListener();
  }

  /**
   * This class should be made &quot;protected&quot; in future releases.
   */
  private class MotifPropertyChangeListener
      extends BasicComboBoxUI.PropertyChangeHandler {

    public void propertyChange(PropertyChangeEvent e) {
      super.propertyChange(e);
      String propertyName = e.getPropertyName();
      if (propertyName == "enabled") {
        if (comboBox.isEnabled()) {
          Component editor = motifGetEditor();
          if (editor != null) {
            editor.setBackground(UIManager.getColor("text"));
          }
        }
      }
    }
  }
}
